﻿using System.Collections.Generic;
using System.ComponentModel;
using Microsoft.Windows.Design.PropertyEditing;

namespace DenisVuyka.Controls.PropertyGrid.Data
{
  /// <summary>
  /// Represents a collection of property item categories.
  /// </summary>
  public class CategoryItemCollection : PropertyItemCollection
  {
    #region Properties

    #region Categories property
    private readonly ObservableList<CategoryEntry> _Categories = new ObservableList<CategoryEntry>();
    
    /// <summary>
    /// Gets the categories.
    /// </summary>
    /// <value>The categories.</value>
    public ObservableList<CategoryEntry> Categories
    {
      get { return _Categories; }
    }
    #endregion

    #endregion

    #region ctors

    /// <summary>
    /// Initializes a new instance of the <see cref="CategoryItemCollection"/> class.
    /// </summary>
    public CategoryItemCollection() : base() { }

    /// <summary>
    /// Initializes a new instance of the <see cref="CategoryItemCollection"/> class.
    /// </summary>
    /// <param name="owner">The owner.</param>
    /// <param name="component">The component.</param>
    public CategoryItemCollection(PropertyGrid owner, object component) : base(owner, component) { }

    #endregion

    #region Initialization

    Dictionary<string, CategoryItem> cache = new Dictionary<string, CategoryItem>();
    HashSet<string> refusedCategories = new HashSet<string>();

    /// <summary>
    /// Initializes the collection.
    /// </summary>
    /// <param name="owner">The owner.</param>
    /// <param name="component">The component.</param>
    protected override void InitializeCollection(PropertyGrid owner, object component)
    {
      cache = new Dictionary<string, CategoryItem>();
      base.InitializeCollection(owner, component);
      cache.Clear();
    }

    /// <summary>
    /// Initializes the property.
    /// </summary>
    /// <param name="property">The property.</param>
    protected override void InitializeProperty(PropertyItem property)
    {
      base.InitializeProperty(property);

      if (refusedCategories.Contains(property.CategoryName)) return;
      
      CategoryItem propertyCategory;
      // Get existing or create a new category
      if (cache.ContainsKey(property.CategoryName))
        propertyCategory = cache[property.CategoryName];
      else
      {
        propertyCategory = Owner.CreateCategory(property.GetAttribute<CategoryAttribute>());

        if (propertyCategory == null)
        {
          refusedCategories.Add(property.CategoryName);
          return;
        }

        cache[propertyCategory.CategoryName] = propertyCategory;
        _Categories.Add(propertyCategory);
      }
      // Add property to the appropriate category
      propertyCategory.AddProperty(property);
    }
    
    #endregion    
  }
}
